﻿namespace Gobang.ToolClass.PVE
{
    public class ManMachine2
    {
        private int[,] ChessBoard;
        private readonly int _chessSize;
        private readonly int[,] score;
        private const int black = -1;
        private const int white = 1;
        private const int board = 0;
        public ManMachine2(int[,] chessBoard)
        {
            ChessBoard = chessBoard;
            _chessSize = ChessBoard.GetLength(0);
            score = new int[_chessSize, _chessSize];
        }
        //机器落子 确定mx my即可  返回true有子可落，返回false无子可落
        public Seat Machine()
        {
            //每次机器落子，都初始化score评分数组
            for (int i = 0; i < _chessSize; i++)
            {
                for (int j = 0; j < _chessSize; j++)
                {
                    score[i, j] = 0;
                }
            }
            int goalX, goalY;
            //每次机器寻找落子位置，评分都重新算一遍，先定义并初始化一些变量
            int bn = 0;                 //五元组中的黑棋数量
            int wn = 0;                 //五元组中的白棋数量
            int tupleScoreTmp = 0;      //五元组得分临时变量

            goalX = -1;                 //初始化目标位置坐标
            goalY = -1;                 //初始化目标位置坐标
            int maxSocre = -1;          //最大分数

            //扫描6个方向
            //1、扫描横向的15行
            for (int i = 0; i < _chessSize; i++)              //对于每一行来说
            {
                for (int j = 0; j < _chessSize - 4; j++)
                {
                    int k = j;
                    while (k < j + 5)   //统计每个五元组的黑白棋数量
                    {
                        if (ChessBoard[i, k] == black)
                            bn++;
                        else if (ChessBoard[i, k] == white)
                            wn++;

                        k++;
                    }

                    tupleScoreTmp = ScoreTable(bn, wn);     //五元组中白子黑子中对应的数量的打分

                    //为该五元组的5个位置添加分数
                    for (k = j; k < j + 5; k++)
                    {
                        score[i, k] += tupleScoreTmp;
                    }

                    //计数器们清零
                    bn = 0;
                    wn = 0;
                    tupleScoreTmp = 0;
                }
            }

            //2、扫描纵向15行
            for (int i = 0; i < _chessSize; i++)
            {
                for (int j = 0; j < _chessSize - 4; j++)
                {
                    int k = j;
                    while (k < j + 5)
                    {
                        if (ChessBoard[k, i] == black)
                            bn++;
                        else if (ChessBoard[k, i] == white)
                            wn++;

                        k++;
                    }

                    tupleScoreTmp = ScoreTable(bn, wn);

                    //为该五元组每个位置添加分数
                    for (k = j; k < j + 5; k++)
                    {
                        score[k, i] += tupleScoreTmp;
                    }

                    //置零
                    bn = 0;
                    wn = 0;
                    tupleScoreTmp = 0;

                }
            }

            //3、扫描右上角到中点方向
            for (int i = _chessSize - 1; i >= 4; i--)
            {
                for (int k = i, j = 0; j < _chessSize && k >= 0; j++, k--)
                {
                    int m = k;
                    int n = j;

                    while (m > k - 5 && k - 5 >= -1)    //这里是-1
                    {
                        if (ChessBoard[m, n] == black)
                            bn++;
                        else if (ChessBoard[m, n] == white)
                            wn++;

                        m--;
                        n++;
                    }

                    if (m == k - 5)
                    {
                        tupleScoreTmp = ScoreTable(bn, wn);

                        for (m = k, n = j; m > k - 5; m--, n++)
                        {
                            score[m, n] += tupleScoreTmp;
                        }
                    }

                    //置零
                    bn = 0;
                    wn = 0;
                    tupleScoreTmp = 0;
                }
            }


            //4、扫描中点到左下角方向
            for (int i = 1; i < _chessSize; i++)
            {
                for (int k = i, j = _chessSize - 1; j >= 0 && k < _chessSize; j--, k++)
                {
                    int m = k;
                    int n = j;

                    while (m < k + 5 && k + 5 <= _chessSize)
                    {
                        if (ChessBoard[n, m] == black)
                            bn++;
                        else if (ChessBoard[n, m] == white)
                            wn++;

                        m++;
                        n--;
                    }

                    if (m == k + 5)
                    {
                        tupleScoreTmp = ScoreTable(bn, wn);
                        for (m = k, n = j; m < k + 5; m++, n--)
                        {
                            score[n, m] += tupleScoreTmp;
                        }
                    }

                    //置零
                    bn = 0;
                    wn = 0;
                    tupleScoreTmp = 0;
                }
            }

            //5、扫描左上角到中点方向
            for (int i = 0; i < _chessSize - 4; i++)
            {
                for (int k = i, j = 0; j < _chessSize && k < _chessSize; j++, k++)
                {
                    int m = k;
                    int n = j;

                    while (m < k + 5 && k + 5 <= _chessSize)
                    {
                        if (ChessBoard[m, n] == black)
                            bn++;
                        else if (ChessBoard[m, n] == white)
                            wn++;

                        m++;
                        n++;
                    }

                    if (m == k + 5)
                    {
                        tupleScoreTmp = ScoreTable(bn, wn);
                        for (m = k, n = j; m < k + 5; m++, n++)
                        {
                            score[m, n] += tupleScoreTmp;
                        }
                    }

                    //置零
                    bn = 0;
                    wn = 0;
                    tupleScoreTmp = 0;
                }
            }


            //6、扫描中点到右下角方向
            for (int i = 1; i < _chessSize - 4; i++)
            {
                for (int k = i, j = 0; j < _chessSize && k < _chessSize; j++, k++)
                {
                    int m = k;
                    int n = j;
                    while (m < k + 5 && k + 5 <= 15)
                    {
                        if (ChessBoard[n, m] == black)
                            bn++;
                        else if (ChessBoard[n, m] == white)
                            wn++;

                        m++;
                        n++;
                    }

                    if (m == k + 5)
                    {
                        tupleScoreTmp = ScoreTable(bn, wn);

                        for (m = k, n = j; m < k + 5; m++, n++)
                        {
                            score[n, m] += tupleScoreTmp;
                        }
                    }

                    //置零
                    bn = 0;
                    wn = 0;
                    tupleScoreTmp = 0;
                }
            }


            //从空位置（能落子的位置）中找到得分最大的位置
            for (int i = 0; i < _chessSize; i++)
            {
                for (int j = 0; j < _chessSize; j++)
                {
                    if (ChessBoard[i, j] == board && score[i, j] > maxSocre)
                    {
                        goalX = i;
                        goalY = j;
                        maxSocre = score[i, j];
                    }
                }
            }

            //没有找到坐标说明平局了

            return new Seat(goalX, goalY, maxSocre);
        }
        /// <summary>
        /// 根据黑子数和白子数，在评分表中获得评分 评分表有10种情况
        /// </summary>
        /// <param name="b"></param>
        /// <param name="w"></param>
        /// <returns></returns>
        private int ScoreTable(int b, int w)
        {
            //1、既有黑子又有白子，判0分
            if (w > 0 && b > 0)
                return 0;

            //2、全部为空，并没有落子，判分为7
            if (w == 0 && b == 0)
                return 7;

            //3、机器落1子，判35分
            if (w == 1)
                return 35;

            //4、机器落2子，判800分
            if (w == 2)
                return 800;

            //5、机器落3子，判15000分
            if (w == 3)
                return 15000;

            //6、机器落4子，判800000分
            if (w == 4)
                return 800000;

            //7、人类落1子，判15分
            if (b == 1)
                return 15;

            //8、人类落2子，判400分
            if (b == 2)
                return 15;

            //9、人类落3子，判1800分
            if (b == 3)
                return 1800;

            //10、人类落4子，判100000
            if (b == 4)
                return 100000;

            return -1;
        }
    }
}
